home *** CD-ROM | disk | FTP | other *** search
- PROGRAM UndoIt;
-
- {Program to test Edit menu including Undo/Redo of previous operation}
-
- {Copyright 1986 (M)agreeable software, inc.}
- { 5925 Magnolia Lane }
- { Plymouth MN 55442 }
-
- {$L UndoIt/Rsrc}
-
-
- {$I Memtypes.Ipas }
- {$I QuickDraw.Ipas}
- {$I OSIntf.Ipas }
- {$I ToolIntf.Ipas }
- {$I PackIntf.Ipas }
-
- CONST MenuBarID = 200;
- FileMenu = 200;
- OpenItem = 1;
- CloseItem = 2;
- QuitItem = 4;
- EditMenu = 201;
- UndoItem = 1;
- CutItem = 3;
- CopyItem = 4;
- PasteItem = 5;
- ClearItem = 6;
- WindowID = 200;
- CantUndoStr = 'Can''t Undo'; {Note double apostrophe}
- UndoStr = 'Undo';
- RedoStr = 'Redo';
- TypingStr = 'Typing';
-
- TYPE EditType = (CantUndo,UndoTyping,UndoCut,UndoCopy,
- UndoPaste,UndoClear,
- RedoTyping,RedoCut,RedoCopy,
- RedoPaste,RedoClear);
-
- {Global variables}
-
- VAR theWindow : WindowPtr; {Main window}
- DisplayTE : TEHandle; {TextEdit record for display}
- ScrapTE : TEHandle; {TextEdit record for scrap}
- fNum : integer; {Ref number for current file}
- QuitFlag : Boolean; {Main event loop exits when TRUE}
- UndoStart : integer; {Start of previous/current selection}
- UndoEnd : integer; {End of previous/current selection}
- CurrentStart : integer; {Backspace point before previous selection}
- EditStatus : EditType;
- FileHandle : MenuHandle;
- EditHandle : MenuHandle;
-
- PROCEDURE Init_MyGlobals;
-
- BEGIN
- QuitFlag:=FALSE;
- theWindow:=NIL; {=NIL if no window opened}
- END; {Init_MyGlobals}
-
- PROCEDURE Open_File;
-
- CONST hCorner = 90;
- vCorner = 90;
- MaxTEText = 32767;
-
- VAR OpenReply : SFReply;
- GetWhere : Point;
- fTypes : SFTypeList;
- OpenErr : OSErr;
- TextRect : Rect;
- TextLength : LongInt;
- TextDest : Ptr;
-
- BEGIN
- GetWhere.h:=hCorner;
- GetWhere.v:=vCorner;
- fTypes[0]:='TEXT';
- OpenErr:=-1; {Set to other than noErr}
- SFGetFile(GetWhere,'',NIL,1,fTypes,NIL,OpenReply);
- WITH OpenReply DO
- IF Good THEN
- OpenErr:=FSOpen(fName,vRefNum,fNum);
- IF OpenErr=noErr THEN
- BEGIN
- theWindow:=GetNewWindow(windowID,NIL,WindowPtr(-1));
- SetPort(theWindow);
- TextRect:=theWindow^.portRect;
- DisplayTE:=TENew(TextRect,TextRect);
- WITH TextRect DO {Make ScrapTE "invisible"}
- BEGIN
- top:=-bottom;
- left:=-right;
- bottom:=0;
- right:=0;
- END;
- ScrapTE:=TENew(TextRect,TextRect);
- OpenErr:=GetEof(fNum,TextLength);
- IF TextLength>MaxTEText THEN {Ensure "not too much" read}
- TextLength:=MaxTEText;
- TextDest:=NewPtr(TextLength);
- OpenErr:=SetFPos(fNum,fsFromStart,0); {Read text from file}
- OpenErr:=FSRead(fNum,TextLength,TextDest);
- TEInsert(TextDest,TextLength,DisplayTE);
- DisposPtr(TextDest);
- EnableItem(FileHandle,CloseItem);
- DisableItem(FileHandle,OpenItem);
- END; {IF OpenErr=noErr}
- END; {Open_File}
-
- PROCEDURE Close_File;
-
- VAR CloseErr : OSErr;
-
- BEGIN
- HideWindow(theWindow);
- TEDispose(DisplayTE);
- TEDispose(ScrapTE);
- DisposeWindow(theWindow);
- theWindow:=NIL;
- CloseErr:=FSClose(fNum);
- EnableItem(FileHandle,OpenItem);
- DisableItem(FileHandle,CloseItem);
- END; {Close_File}
-
- PROCEDURE File_Manager(MenuItem:integer;VAR QuitFlag:Boolean);
-
- BEGIN
- CASE MenuItem OF
- OpenItem:Open_File;
- CloseItem:Close_File;
- QuitItem:
- BEGIN
- IF theWindow<>NIL THEN
- Close_File;
- QuitFlag:=TRUE;
- END;
- OTHERWISE
- END; {CASE MenuItem}
- END; {File_Manager}
-
- PROCEDURE Reset_EditMenu(UndoState:EditType);
-
- VAR theStr : Str255;
- theItem : integer;
-
- BEGIN
- IF TEGetScrapLen>0 THEN {Set Paste according to scrap}
- EnableItem(EditHandle,PasteItem)
- ELSE
- DisableItem(EditHandle,PasteItem);
- WITH DisplayTE^^ DO
- IF SelStart<SelEnd THEN {Set Cut,Copy,Clear according}
- BEGIN {to selection size }
- EnableItem(EditHandle,CutItem);
- EnableItem(EditHandle,CopyItem);
- EnableItem(EditHandle,ClearItem);
- END
- ELSE
- BEGIN
- DisableItem(EditHandle,CutItem);
- DisableItem(EditHandle,CopyItem);
- DisableItem(EditHandle,ClearItem);
- END;
- EditStatus:=UndoState;
- IF EditStatus=CantUndo THEN
- theStr:=CantUndoStr
- ELSE IF EditStatus IN [UndoTyping,RedoTyping] THEN
- theStr:=TypingStr
- ELSE
- BEGIN
- CASE EditStatus OF {Get item number to Undo/Redo}
- UndoCut,RedoCut:
- theItem:=CutItem;
- UndoCopy,RedoCopy:
- theItem:=CopyItem;
- UndoPaste,RedoPaste:
- theItem:=PasteItem;
- UndoClear,RedoClear:
- theItem:=ClearItem;
- OTHERWISE
- END; {CASE EditStatus}
- GetItem(EditHandle,theItem,theStr);
- END; {IF EditStatus}
- IF EditStatus IN [UndoTyping..UndoClear] THEN
- theStr:=Concat(UndoStr,' ',theStr)
- ELSE IF EditStatus IN [RedoTyping..RedoClear] THEN
- theStr:=Concat(RedoStr,' ',theStr);
- SetItem(EditHandle,UndoItem,theStr); {Reset Undo item}
- IF EditStatus=CantUndo THEN {Disable Can't Undo, Enable Undo/Redo}
- DisableItem(EditHandle,UndoItem)
- ELSE
- EnableItem(EditHandle,UndoItem);
- END; {Reset_EditMenu}
-
- PROCEDURE Save_Clipboard;
-
- BEGIN
- TESetSelect(0,ScrapTE^^.TELength,ScrapTE);
- TEPaste(ScrapTE);
- END; {Save_Clipboard}
-
- PROCEDURE Restore_Clipboard;
-
- BEGIN
- TESetSelect(0,ScrapTE^^.TELength,ScrapTE);
- TECut(ScrapTE); {Also clears ScrapTE}
- END; {Restore_Clipboard}
-
- PROCEDURE Delete_ScrapTE;
-
- BEGIN
- TESetSelect(0,ScrapTE^^.TELength,ScrapTE);
- TEDelete(ScrapTE);
- END; {Delete_ScrapTE}
-
- PROCEDURE Save_EndPoints;
-
- BEGIN
- WITH DisplayTE^^ DO {Save selection points}
- BEGIN
- UndoStart:=SelStart;
- UndoEnd:=SelEnd;
- CurrentStart:=UndoStart;
- END;
- END; {Save_EndPoints}
-
- PROCEDURE Save_Selection(theStart,theEnd:integer); {Selection to ScrapTE}
-
- BEGIN
- IF theStart<theEnd THEN
- BEGIN
- HLock(Handle(DisplayTE));
- WITH DisplayTE^^ DO
- BEGIN
- HLock(hText);
- TEInsert(Ptr(Ord4(hText^)+theStart),
- theEnd-theStart,ScrapTE);
- HUnlock(hText);
- END;
- HUnlock(Handle(DisplayTE));
- END;
- END; {Save_Selection}
-
- PROCEDURE Restore_Selection(theLength:integer); {ScrapTE to selection}
-
- BEGIN
- IF theLength>0 THEN
- BEGIN
- HLock(Handle(ScrapTE));
- WITH ScrapTE^^ DO
- BEGIN
- HLock(hText); {ScrapTE to insertion point}
- TEInsert(Ptr(Ord4(hText^)),theLength,DisplayTE);
- HUnlock(hText);
- END;
- HUnlock(Handle(ScrapTE));
- END;
- END; {Restore_Selection}
-
- PROCEDURE Cut;
-
- BEGIN
- Save_EndPoints;
- Save_Clipboard;
- TECut(DisplayTE); {Cut selection to clipboard}
- Reset_EditMenu(UndoCut);
- END; {Cut}
-
- PROCEDURE Copy;
-
- BEGIN
- Save_EndPoints;
- Save_Clipboard; {Save old clipboard}
- TECopy(DisplayTE); {Copy selection to clipboard}
- Reset_EditMenu(UndoCopy);
- END; {Copy}
-
- PROCEDURE Paste;
-
- BEGIN
- Save_EndPoints;
- Delete_ScrapTE;
- Save_Selection(UndoStart,UndoEnd);
- TEPaste(DisplayTE); {Paste selection to clipboard}
- Reset_EditMenu(UndoPaste);
- END; {Paste}
-
- PROCEDURE Clear;
-
- BEGIN
- Save_EndPoints;
- Delete_ScrapTE;
- Save_Selection(UndoStart,UndoEnd);
- TEDelete(DisplayTE); {Delete current selection}
- Reset_EditMenu(UndoClear);
- END; {Clear}
-
- PROCEDURE Undo_Cut;
-
- BEGIN
- TEPaste(DisplayTE); {Restore text}
- TESetSelect(UndoStart,UndoEnd,DisplayTE); {Reset selection}
- Restore_Clipboard;
- Reset_EditMenu(RedoCut);
- END; {Undo_Cut}
-
- PROCEDURE Undo_Copy;
-
- BEGIN
- Restore_Clipboard;
- Reset_EditMenu(RedoCopy);
- END; {Undo_Copy}
-
- PROCEDURE Undo_Paste;
-
- BEGIN
- TESetSelect(UndoStart,DisplayTE^^.SelEnd,DisplayTE); {Delete pasted text}
- {UndoStart is also beginning of pasted text}
- TEDelete(DisplayTE);
- Restore_Selection(ScrapTE^^.TELength);
- TESetSelect(UndoStart,UndoEnd,DisplayTE); {Reset selection}
- Delete_ScrapTE;
- Reset_EditMenu(RedoPaste);
- END; {Undo_Paste}
-
- PROCEDURE Undo_Clear;
-
- BEGIN
- Restore_Selection(ScrapTE^^.TELength);
- TESetSelect(UndoStart,UndoEnd,DisplayTE); {Reset selection}
- Delete_ScrapTE;
- Reset_EditMenu(RedoClear);
- END; {Undo_Clear}
-
- PROCEDURE Undo_Typing;
-
- VAR scrapLength : integer;
- TypingEnd : integer;
- theText : Handle;
-
- BEGIN
- scrapLength:=ScrapTE^^.TELength; {Put new typing at end of scrap}
- TESetSelect(scrapLength,scrapLength,ScrapTE);
- TypingEnd:=DisplayTE^^.selEnd;
- IF CurrentStart<TypingEnd THEN
- BEGIN
- Save_Selection(CurrentStart,TypingEnd);
- TESetSelect(CurrentStart,TypingEnd,DisplayTE);
- TEDelete(DisplayTE); {Delete new typing}
- END; {IF CurrentStart<TypingEnd}
- Restore_Selection(scrapLength); {Put original selection back}
- TESetSelect(UndoStart,UndoEnd,DisplayTE);
- TESetSelect(0,scrapLength,ScrapTE); {Delete previous from scrap}
- TEDelete(ScrapTE);
- Reset_EditMenu(RedoTyping);
- END; {Undo_Typing}
-
- PROCEDURE Redo_Typing;
-
- VAR scrapLength : integer;
- TypingEnd : integer;
- theText : Handle;
-
- BEGIN
- scrapLength:=ScrapTE^^.TELength; {Put old selection at end of }
- TESetSelect(scrapLength,scrapLength,ScrapTE); {ScrapTE}
- TypingEnd:=DisplayTE^^.selEnd;
- IF CurrentStart<TypingEnd THEN
- BEGIN
- Save_Selection(CurrentStart,TypingEnd);
- TESetSelect(CurrentStart,TypingEnd,DisplayTE);
- TEDelete(DisplayTE); {Delete old selection}
- END; {IF CurrentStart<TypingEnd}
- Restore_Selection(scrapLength); {Move new typing to DisplayTE}
- TESetSelect(0,scrapLength,ScrapTE);
- TEDelete(ScrapTE); {Delete new typing from ScrapTE}
- Reset_EditMenu(UndoTyping);
- END; {Redo_Typing}
-
- PROCEDURE Undo;
-
- BEGIN
- CASE EditStatus OF
- UndoCut:
- Undo_Cut;
- UndoCopy:
- Undo_Copy;
- UndoPaste:
- Undo_Paste;
- UndoClear:
- Undo_Clear;
- UndoTyping:
- Undo_Typing;
- RedoCut:
- Cut;
- RedoCopy:
- Copy;
- RedoPaste:
- Paste;
- RedoClear:
- Clear;
- RedoTyping:
- Redo_Typing;
- OTHERWISE
- END; {CASE EditStatus}
- END; {Undo}
-
-
- PROCEDURE Edit_Manager (MenuItem:integer);
-
- BEGIN
- CASE MenuItem OF
- UndoItem:
- Undo;
- CutItem:
- Cut;
- CopyItem:
- Copy;
- PasteItem:
- Paste;
- ClearItem:
- Clear;
- END; {CASE MenuItem}
- END; {Edit_Manager}
-
- PROCEDURE Menu_Selector(where:Point;VAR QuitFlag:boolean);
-
- VAR theCode : LongInt;
- MenuNum : integer;
- MenuItem : integer;
-
- BEGIN
- theCode:=MenuSelect(where);
- MenuNum:=HiWord(theCode);
- MenuItem:=LoWord(theCode);
- Case MenuNum OF
- FileMenu:File_Manager(MenuItem,QuitFlag);
- EditMenu:Edit_Manager(MenuItem);
- OTHERWISE
- END; {CASE OF MenuNum}
- HiliteMenu(0);
- END; {Menu_Selector}
-
- PROCEDURE TE_Selector(where:Point;extend:Boolean);
-
- BEGIN
- SetPort(theWindow); {Ensure currentport is the text window}
- GlobaltoLocal(where); {Put mouse point local to text window }
- TEClick(where,extend,DisplayTE);
- Reset_EditMenu(CantUndo);
- END; {TE_Selector}
-
- PROCEDURE Typist(EventMessage:LongInt);
-
- CONST Return = $0D;
- Enter = $03;
- Backspace = $08;
- Tab = $09;
-
- TYPE Codes = 0..255;
-
- VAR KeyCode : integer;
- CharIn : Char;
- CharH : CharsHandle;
- AllowedCodes : SET OF Codes;
-
- BEGIN
- KeyCode:=BitAnd(EventMessage,charCodeMask);
- AllowedCodes:=[$20..$7F,Return,Enter,Backspace,Tab];
- {May be erroneous if used directly in TML Pascal 1.11 IF statement}
- {See letter from Christopher Dunn in July 1986 MacTutor}
- IF KeyCode in AllowedCodes THEN
- CharIn:=chr(KeyCode)
- ELSE
- KeyCode:=0; {Use KeyCode=0 as test to bypass sections}
- IF EditStatus<>UndoTyping THEN
- IF KeyCode<>0 THEN
- BEGIN
- Save_EndPoints;
- Delete_ScrapTE;
- Save_Selection(UndoStart,UndoEnd);
- END; {IF EditStatus<>UndoTyping,IF KeyCode<>0}
- IF KeyCode=Backspace THEN
- WITH DisplayTE^^ DO
- IF SelStart>0 THEN
- IF SelEnd<=CurrentStart THEN
- BEGIN
- CharH:=TEGetText(DisplayTE);
- {Get the text as a character array}
- CurrentStart:=CurrentStart-1;
- TESetSelect(0,0,ScrapTE);
- TEKey(CharH^^[SelStart-1],ScrapTE);
- END;
- IF KeyCode<>0 THEN
- BEGIN
- TEKey(CharIn,DisplayTE);
- If EditStatus<>UndoTyping THEN
- Reset_EditMenu(UndoTyping);
- END;
- END; {Typist}
-
- PROCEDURE MainEventLoop;
-
- VAR MainEvent : EventRecord;
- theCode : integer;
- extend : Boolean;
- anyWindow : WindowPtr;
-
- BEGIN {MainEventLoop}
- REPEAT
- IF GetNextEvent(everyEvent,MainEvent) THEN
- CASE MainEvent.what OF
- activateEvt:
- IF theWindow<>NIL THEN
- TEActivate(DisplayTE);
- mouseDown:
- BEGIN
- theCode:=FindWindow(MainEvent.where,anyWindow);
- CASE theCode OF
- inMenuBar:
- Menu_Selector(MainEvent.where,QuitFlag);
- inContent: {Assume only one window}
- BEGIN
- extend:=(BitAnd(MainEvent.modifiers,ShiftKey)<>0);
- {If user holding shift key, then extend selection}
- TE_Selector(MainEvent.where,extend);
- END;
- OTHERWISE {Ignore}
- END; {CASE theCode}
- END; {mouseDown}
- keyDown,autoKey: {ignores command key}
- IF theWindow<>NIL THEN
- Typist(MainEvent.message);
- OTHERWISE
- END; {IF GetNextEvent, CASE MainEvent.what}
- IF theWindow<>NIL THEN {If window exists, blink caret}
- TEIdle(DisplayTE);
- UNTIL QuitFlag;
- END; {MainEventLoop}
-
- FUNCTION Init_MyMenus:Boolean;
-
- CONST MenuBarId = 200;
-
- VAR theMenuBar : Handle; {MBAR resource points to menus}
-
- BEGIN
- Init_MyMenus:=FALSE; {Assume menus not initialized}
- theMenuBar:=GetNewMBar(MenuBarId);
- IF theMenuBar<>NIL THEN
- BEGIN
- SetMenuBar(theMenuBar);
- DrawMenuBar;
- FileHandle:=GetMHandle(FileMenu);
- EditHandle:=GetMHandle(EditMenu);
- Init_MyMenus:=TRUE;
- END;
- END; {Init_MyMenus}
-
- BEGIN {Main Program}
- InitGraf(@thePort);
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(NIL);
- InitCursor;
- Init_MyGlobals;
- FlushEvents(EveryEvent,0);
- IF Init_MyMenus THEN
- MainEventLoop;
- END. {Main Program}